%%%-----------------------------------------------------------------------------
%%% @doc
%%% schema_db.
%%%
%%% @end
%%%-----------------------------------------------------------------------------
-module(schema_db).


-export([stop/0, mnesia_init/1]).
-export([disc_dispatch/1, ram_dispatch/1, remote_dispatch/1]).

stop() ->
	mnesia:stop().

% %% mnesia初始化
mnesia_init(Cluster) ->
    sync_master_node(Cluster),
    io:format("mnesia start~n"),
    ok.

sync_master_node(Cluster) ->
    case connect_nodes(Cluster) of
        ignore -> ok;
        _ ->
            case get_node_type() of
                ram ->
                    lists:map(fun(TableName) ->
                        mnesia:add_table_copy(TableName, node(), ram_copies)
                    end, get_all_tables_def());
                disc ->
                    mnesia:change_table_copy_type(schema, node(), disc_copies),
                    lists:map(fun(TableName) ->
                                mnesia:add_table_copy(TableName, node(), disc_copies)
                            end, get_all_tables_def());
                disc_only ->
                    mnesia:change_table_copy_type(schema, node(), disc_only_copies),
                    lists:map(fun(TableName) ->
                                  mnesia:add_table_copy(TableName, node(), disc_only_copies)
                              end, get_all_tables_def());                    
                _ -> 
                    ok
            end
    end.

extra_db_nodes(Nodes) ->
    mnesia:change_config(extra_db_nodes, Nodes).

get_node_type() ->
    [App, _] = string:tokens(atom_to_list(node()), "@"),
    App2 = case App of
        "im_server" ->
            "emqttd";
        _ ->
            App
    end,
    {ok, Cluster} = application:get_env(list_to_atom(App2), cluster),
    {Type, _, _} = lists:keyfind(node(), 2, Cluster),
    Type.

get_running_node(Ret, []) ->
    Ret;
get_running_node(Ret, [{_, Node, _}|T]) ->
    if
        Node =/= node() ->
            case net_adm:ping(Node) of
                pang ->
                    %% node down
                    get_running_node(Ret, T);
                pong ->
                    %% success
                    get_running_node([Node|Ret], T)
            end;
        true ->
            get_running_node(Ret, T)
    end.

connect_nodes(Cluster) ->
    case get_running_node([], Cluster) of
        [] ->
            ignore;
        Nodes ->
            extra_db_nodes(Nodes)
    end.    

get_all_tables_def() ->
     [users, topic, topic_subscriber, nodes,
      off_msg, user_id, node_id, off_msg_id, 
      user_info, url_map].


disc_dispatch(Cluster) ->
    mnesia:unsubscribe(system),
    mnesia_init(Cluster),
    mnesia:subscribe(system).

ram_dispatch(Cluster) ->
    mnesia:unsubscribe(system),
    mnesia_init(Cluster),
    mnesia:subscribe(system).

remote_dispatch(Cluster) ->
    mnesia:unsubscribe(system),
    mnesia_init(Cluster),
    mnesia:subscribe(system).